if (typeof inweo == "undefined") {
	window.inweo = function() {
		this.version = 0.1;
		if (typeof window.inweo.registry != "object") {
			this.__constructor();
		}
	}
	inweo.prototype.performance = function(fn) {
		var args = Array.prototype.slice.call(arguments);
		args = args.slice(1);
		var start = new Date();
		for (var i = 0; i < 10000; i++) {
			fn.apply(this, args);
		}
		return parseFloat(new Date() - start);
	}
	inweo.prototype.assert = function(condition, message) {
		if (typeof message != "string") {
			if (!condition) {
				return false;
			} else {
				return true;
			}
		} else {
			try {
				if (!condition) {
					throw {
						message: message
					};
				}
			} catch (e) {
				inweo.error(e.message);
			}
		}
	}
	inweo.prototype.log =  function() {
		inweo.debug.apply(this, arguments);
	}
	inweo.prototype.debug = function(string) {
		if (inweo.get("sdk") != true) {
			return;
		}
		if (typeof window.console != "undefined") {
			try {
				console.log.apply(this, arguments);
			} catch (e) {
				console.log(string);
			}
		}
	}
	inweo.prototype.detectBrowser = function() {
		//class instead of id?
		if (!document.body.id) {
			// at moment of writing this, I only care about those four browsers (and google chrome)
			var browser = "Unknown";
			if (navigator.appName == "Netscape") {
				browser = "gecko";
			} else if (navigator.appName == "Microsoft Internet Explorer") {
				browser = "ie";
			} else if (navigator.appName == "Opera") {
				browser = "opera";
			} else if (navigator.vendor == "Apple Computer, Inc.") {
				browser = "webkit";
			}
			document.body.id = browser;
			window.browser = browser;
		}
		return document.body.id;
	}
	inweo.prototype.execute = function(fns, context) {
		var args = Array.prototype.slice.call(arguments);
		args = args.slice(2);
		fns.each(function(fn) {
			fn.apply(context, args);
		});
	}
	inweo.prototype.error = function(string) {
		if (typeof window.console != "undefined") {
			try {
				console.error.apply(this, arguments);
			} catch (e) {
				console.error(string);
			}
		} else {
			alert(string);
		}
	}	
	inweo.prototype.get = function(variable) {
		return window.inweo.registry[variable];
	}
	inweo.prototype.message = function(object, message, data) {
		try {
			object.__messageCallback.call(object, message, data);
		} catch(e) { /* object did not implement method __message */ }
	},
	inweo.prototype.postMessage = function(object) {
		var args = Array.prototype.slice.call(arguments);
		args = args.slice(1);
		try {
			object.onMessage.apply(object, args);
		} catch(e) {}
	},
	inweo.prototype.skin = function(theme) {
		inweo.loadCss(inweo.get("path") + "skin/" + theme + "/" + theme + ".css");
	},
	inweo.prototype.loadCss = function(url) {
		var link = document.createElement("link");
		link.href = url;
		link.type = "text/css";
		link.rel = "stylesheet";
		var head = document.getElementsByTagName("head")[0];
		head.appendChild(link);
	}
	inweo.prototype.loadJs = function(url, callback) {
		var request = null;
		request = new XMLHttpRequest();
		request.open("GET", url, false);
		/*
		setTimeout(function () {
			request.abort();
		}, 60000);
		//*/
		request.send(null);
		if (navigator.appName == "Microsoft Internet Explorer") {
			if (!request.getResponseHeader("Date")) {
				var cached = request;
				request = new XMLHttpRequest();
				var ifModifiedSince = cached.getResponseHeader("Last-Modified");
				ifModifiedSince = (ifModifiedSince) ? ifModifiedSince : new Date(0); // January 1, 1970
				request.open("GET", url, false);
				request.setRequestHeader("If-Modified-Since", ifModifiedSince);
				request.send(null);
				if (request.status == 304) {
					request = cached;
				}
			}
		}
		var script = document.createElement("script");
		script.type = "text/javascript";
		if (navigator.appName != "Microsoft Internet Explorer") {
			script.appendChild(document.createTextNode(request.responseText));
		} else {
			script.text = request.responseText;
		}
		var head = document.getElementsByTagName("head")[0];
		head.appendChild(script);
		if (callback != null) {
			callback.call(this);
		}
	}
	inweo.prototype.__constructor = function() {
		this.detectBrowser();
		window.inweo					= this;
		window.inweo.widgets			= [];
		window.inweo.core				= [];
		window.inweo.utils				= [];
		window.inweo.registry			= [];
		window.inweo.registry.sdk		= true;
		window.inweo.registry.path		= "";

		var loadTag = false;
		var scripts = document.getElementsByTagName("head")[0].getElementsByTagName("script");
		var i = scripts.length;
		while (i--) {
			var src = scripts[i].src;
			if (src.indexOf("inweo.js") != -1) {
				window.inweo.registry.path = src.substr(0, src.indexOf("inweo.js"));
				var tag = scripts[i].getAttribute("tag");
				if (tag == 1) {
					loadTag = true;
				}
			}
		}

		var path = inweo.get("path");
		//inweo.loadJs(path + "lib/mootools.js");
		inweo.loadCss(path + "skin/widget.css");
		inweo.loadJs(path + "core/event.js");
		inweo.loadJs(path + "core/widget.js");
		if (loadTag === true) {
			inweo.loadJs(path + "core/tag.js", function() {
				new inweo.core.tag(true);
			});
		}

		if (window.main) {
			window.main.apply(document.body);
		}
		
		window.unload = function() {
			delete window.inweo;
		}
	}
	inweo.prototype.require = function(object, type) {
		// mess, it should be inweo.require("namespace.object"); e.g. inweo.require("inweo.widgets.label");
		// mess, it should check if object already downloaded
		// if (inweo.get("inweo.widgets.label") != true) {
		if (inweo.get("require_" + object) != true) {
			inweo.set("require_" + object, true);
			if (type == "utils") {
				this.loadJs(inweo.get("path") + "utils/" + object + "/" + object + ".js");
			} else {
				this.loadJs(inweo.get("path") + "widgets/" + object + "/" + object + ".js");
				this.loadCss(inweo.get("path") + "widgets/" + object + "/" + object + ".css");
			}	
		}
	}
	inweo.prototype.set = function(variable, value) {
		// @todo: listen to a key and execute callback on change... how?
		window.inweo.registry[variable] = value;
	}
	if (document.addEventListener) {
		// firefox, safari, opera and chrome got it!
		document.addEventListener("DOMContentLoaded", function() {
			new inweo();
		}, false);
	} else { // then ie
		window.onload = function() {
			new inweo();
		}
	}

	inweo.prototype.getCSS = function(element, style) {
		var value = null;
		if (element.currentStyle) {
			value = element.currentStyle[style.toCamelCase()];
		} else if (window.getComputedStyle) {
			value = document.defaultView.getComputedStyle(element, null).getPropertyValue(style);
		}
		return value;
	}
	/*
	// DOM HTML
	Element.prototype.getCSS = function(style) {
		var value = null;
		if (this.currentStyle) {
			value = this.currentStyle[style.toCamelCase()];
		} else if (window.getComputedStyle) {
			value = document.defaultView.getComputedStyle(this, null).getPropertyValue(style);
		}
		return value;
	}
	//*/
	// String
	String.prototype.toCamelCase = function toCamelCase() {
		return this.replace(/\-(.)/g, function(m, l) {
			return l.toUpperCase();
		});
	}
}